This exercise is based on the tutorial “Analysing massive open human mobility data in R using spanishoddata, duckdb and flowmaps” by Egor Kotov.
This is a more advanced exercise that benefits from having a fast internet connection, decent compute resources, and an interest in the Iberian Peninsula.
The downloaded binary packages are in
/var/folders/g5/tzxh_kjx6tq7lqcgzp9mf4qm0000gn/T//RtmplHIYVI/downloaded_packages
rm(packages)
# This code chunk creates an interactive flow map for Seville# demonstrating animation and time-filtering capabilities# It is based on the vignette from the rOpenSpain/spanishoddata package.# --- 1. Load necessary libraries ---library(spanishoddata)library(flowmapblue)library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.4 ✔ tidyr 1.3.1
✔ purrr 1.0.4
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sf)
Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
# --- 2. Set up Mapbox Access Token (required for the basemap) ---# Get a free token from https://account.mapbox.com/access-tokens/Sys.setenv(MAPBOX_TOKEN ="pk.eyJ1IjoiZWxsYXN0dWJiaW5ncyIsImEiOiJjbWZxa2tvZTEwdGl2MmtyMmpuMnNpNzB2In0.O1IVyRdxM30sm60LFb6f1w")# --- 3. Download and prepare the data ---# Get OD data for a typical day in 2021zones <-spod_get_zones(zones ="distr", ver =2)
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Fetching latest metadata from AmazonS3 (v2)...
Cached new data to: /var/folders/g5/tzxh_kjx6tq7lqcgzp9mf4qm0000gn/T/RtmplHIYVI/metadata_cache/metadata_s3_v2_2025-09-19.rds
Downloading missing zones data...
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Fetching latest metadata from AmazonS3 (v1)...
Cached new data to: /var/folders/g5/tzxh_kjx6tq7lqcgzp9mf4qm0000gn/T/RtmplHIYVI/metadata_cache/metadata_s3_v1_2025-09-19.rds
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Deleting source `/var/folders/g5/tzxh_kjx6tq7lqcgzp9mf4qm0000gn/T/RtmplHIYVI/clean_data/v2/zones/distritos_mitma.gpkg' failed
Writing layer `distritos_mitma' to data source
`/var/folders/g5/tzxh_kjx6tq7lqcgzp9mf4qm0000gn/T/RtmplHIYVI/clean_data/v2/zones/distritos_mitma.gpkg' using driver `GPKG'
Writing 3909 features with 9 fields and geometry type Unknown (any).
valid_dates <-spod_get_valid_dates(2)
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning: `time slot` was deprecated in spanishoddata 0.1.0.9000.
ℹ Please use `hour` instead.
ℹ `time_slot` column in origin destination data is now called `hour`.
`time_slot` will be available in addition to `hour` and contain the same data
in the outputs of `spod_get()` and `spod_convert()` until the end of 2025.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Data version detected from dates: 2
Warning in spod_get_data_dir(): Warning: SPANISH_OD_DATA_DIR is not set. Using the temporary directory, which is not recommended, as the data will be deleted when the session ends.
To set the data directory, use `spod_set_data_dir('/path/to/data')` or set SPANISH_OD_DATA_DIR permanently in the environment by editing the `.Renviron` file locally for current project with `usethis::edit_r_environ('project')` or `file.edit('.Renviron')` or globally for all projects with `usethis::edit_r_environ('user')` or `file.edit('~/.Renviron')`.
Using memory-cached available data from S3
Downloading approximately 0.67 GB of data.
Retrieved data for requested dates.
# --- 4. Process the OD data to create a timestamp for each flow ---od_data_time <- flows |>mutate(time =as.POSIXct(paste0(date, "T", hour, ":00:00"))) |>group_by(origin = id_origin, dest = id_destination, time) |>summarise(count =sum(n_trips, na.rm =TRUE), .groups ="drop") |>collect()
# --- 5. Filter data for the Seville region ---# Identify zones corresponding to Sevillezones_seville <- zones |>filter(grepl("^Sevilla distrito", name, ignore.case =TRUE)) mapview::mapview(zones_seville)
# Create a 10km buffer to define the Functional Urban Area (FUA)zones_seville_fua <- zones[st_buffer(zones_seville, dist =10000), ]plot(st_geometry(zones_seville_fua))
# Prepare the location data (centroids) for the flow mapsf::sf_use_s2(FALSE)
Warning: st_centroid assumes attributes are constant over geometries
Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
of_largest_polygon): st_centroid does not give correct centroids for
longitude/latitude data
# Filter the time-based OD data to include only flows within the Sevilleflows_seville_time <- od_data_time |>filter(origin %in% zones_seville_fua$id & dest %in% zones_seville_fua$id)#Filter the time-based OD data to include only flows within the Seville FUAflows_seville_time <- od_data_time |>filter(origin %in% zones_seville_fua$id & dest %in% zones_seville_fua$id)
# --- 6. Generate the interactive flow map ---# Create the plot with animation and clustering enabled. # The resulting map will have a time slider to filter flows by hour.flowmap_seville_interactive <-flowmapblue(locations = locations_seville,flows = flows_seville_time,mapboxAccessToken =Sys.setenv(MAPBOX_TOKEN ="pk.eyJ1IjoiZWxsYXN0dWJiaW5ncyIsImEiOiJjbWZxa2tvZTEwdGl2MmtyMmpuMnNpNzB2In0.O1IVyRdxM30sm60LFb6f1w"),darkMode =TRUE,animation =FALSE,clustering =TRUE)# Display the mapflowmap_seville_interactive